From 5d8d99be048899c0438dab4e726238eb97b0440f Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 1 Mar 2007 14:51:12 +0000 Subject: [PATCH] Fully reset the xenstore connection when a domain is (re)introduced to xenstored. Signed-off-by: Keir Fraser --- tools/xenstore/xenstored_domain.c | 27 ++++++++++++++++++++++---- tools/xenstore/xenstored_transaction.c | 16 +++++++++++++++ tools/xenstore/xenstored_transaction.h | 3 +++ tools/xenstore/xenstored_watch.c | 11 +++++++++++ tools/xenstore/xenstored_watch.h | 2 ++ 5 files changed, 55 insertions(+), 4 deletions(-) diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_domain.c index ba3507fdfc..5249ef6d56 100644 --- a/tools/xenstore/xenstored_domain.c +++ b/tools/xenstore/xenstored_domain.c @@ -28,6 +28,7 @@ #include "talloc.h" #include "xenstored_core.h" #include "xenstored_domain.h" +#include "xenstored_transaction.h" #include "xenstored_watch.h" #include "xenstored_test.h" @@ -289,6 +290,26 @@ static struct domain *find_domain_by_domid(unsigned int domid) return NULL; } +static void domain_conn_reset(struct domain *domain) +{ + struct connection *conn = domain->conn; + struct buffered_data *out; + + conn_delete_all_watches(conn); + conn_delete_all_transactions(conn); + + while ((out = list_top(&conn->out_list, struct buffered_data, list))) { + list_del(&out->list); + talloc_free(out); + } + + talloc_free(conn->in->buffer); + memset(conn->in, 0, sizeof(*conn->in)); + conn->in->inhdr = true; + + domain->interface->req_cons = domain->interface->req_prod = 0; + domain->interface->rsp_cons = domain->interface->rsp_prod = 0; +} /* domid, mfn, evtchn, path */ void do_introduce(struct connection *conn, struct buffered_data *in) @@ -342,7 +363,7 @@ void do_introduce(struct connection *conn, struct buffered_data *in) talloc_steal(domain->conn, domain); fire_watches(conn, "@introduceDomain", false); - } else if (domain->mfn == mfn) { + } else if ((domain->mfn == mfn) && (domain->conn != conn)) { /* Use XS_INTRODUCE for recreating the xenbus event-channel. */ if (domain->port) xc_evtchn_unbind(xce_handle, domain->port); @@ -354,9 +375,7 @@ void do_introduce(struct connection *conn, struct buffered_data *in) return; } - /* Rings must be quiesced. */ - domain->interface->req_cons = domain->interface->req_prod = 0; - domain->interface->rsp_cons = domain->interface->rsp_prod = 0; + domain_conn_reset(domain); send_ack(conn, XS_INTRODUCE); } diff --git a/tools/xenstore/xenstored_transaction.c b/tools/xenstore/xenstored_transaction.c index 69cc520bb9..cf10ecc348 100644 --- a/tools/xenstore/xenstored_transaction.c +++ b/tools/xenstore/xenstored_transaction.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -211,6 +212,21 @@ void do_transaction_end(struct connection *conn, const char *arg) send_ack(conn, XS_TRANSACTION_END); } +void conn_delete_all_transactions(struct connection *conn) +{ + struct transaction *trans; + + while ((trans = list_top(&conn->transaction_list, + struct transaction, list))) { + list_del(&trans->list); + talloc_free(trans); + } + + assert(conn->transaction == NULL); + + conn->transaction_started = 0; +} + /* * Local variables: * c-file-style: "linux" diff --git a/tools/xenstore/xenstored_transaction.h b/tools/xenstore/xenstored_transaction.h index 1fc30dff50..ecbae47f2d 100644 --- a/tools/xenstore/xenstored_transaction.h +++ b/tools/xenstore/xenstored_transaction.h @@ -33,4 +33,7 @@ void add_change_node(struct transaction *trans, const char *node, /* Return tdb context to use for this connection. */ TDB_CONTEXT *tdb_transaction_context(struct transaction *trans); + +void conn_delete_all_transactions(struct connection *conn); + #endif /* _XENSTORED_TRANSACTION_H */ diff --git a/tools/xenstore/xenstored_watch.c b/tools/xenstore/xenstored_watch.c index 3de6e7ace8..4d1a6d5bfb 100644 --- a/tools/xenstore/xenstored_watch.c +++ b/tools/xenstore/xenstored_watch.c @@ -185,6 +185,17 @@ void do_unwatch(struct connection *conn, struct buffered_data *in) send_error(conn, ENOENT); } +void conn_delete_all_watches(struct connection *conn) +{ + struct watch *watch; + + while ((watch = list_top(&conn->watches, struct watch, list))) { + list_del(&watch->list); + talloc_free(watch); + domain_watch_dec(conn); + } +} + #ifdef TESTING void dump_watches(struct connection *conn) { diff --git a/tools/xenstore/xenstored_watch.h b/tools/xenstore/xenstored_watch.h index 2eccff9476..6125ff3886 100644 --- a/tools/xenstore/xenstored_watch.h +++ b/tools/xenstore/xenstored_watch.h @@ -30,4 +30,6 @@ void fire_watches(struct connection *conn, const char *name, bool recurse); void dump_watches(struct connection *conn); +void conn_delete_all_watches(struct connection *conn); + #endif /* _XENSTORED_WATCH_H */ -- 2.30.2